<!DOCTYPE HTML>
<html lang="en">
<head>
<title>Loop (files &amp; folders) - Syntax &amp; Usage | AutoHotkey</title>
<meta name="description" content="The Loop Files statement retrieves the specified files or folders, one at a time." />
<meta name="ahk:equiv-v2" content="commands/LoopFiles.htm" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>Loop (files &amp; folders)</h1>
<p>Retrieves the specified files or folders, one at a time.</p>

<h2 id="new">New Syntax <span class="ver">[v1.1.21+]</span></h2>
<pre class="Syntax"><span class="func">Loop, Files</span>, FilePattern <span class="optional">, Mode</span></pre>

<h3>Parameters</h3>
<dl>

  <dt>Files</dt>
  <dd><p>The literal word <code>Files</code> (case-insensitive). This cannot be a variable or expression.</p></dd>

  <dt>FilePattern</dt>
  <dd><p>The name of a single file or folder, or a wildcard pattern such as <code>C:\Temp\*.tmp</code>. <em>FilePattern</em> is assumed to be in <a href="../Variables.htm#WorkingDir">A_WorkingDir</a> if an absolute path isn't specified.</p>
      <p>Both asterisks and question marks are supported as wildcards. A match occurs when the pattern appears in either the file's long/normal name or its <a href="#LoopFileShortName">8.3 short name</a>.</p>
      <p>If this parameter is a single file or folder (i.e. no wildcards) and <em>Mode</em> includes <code>R</code>, more than one match will be found if the specified file name appears in more than one of the folders being searched.</p></dd>

  <dt>Mode</dt>
  <dd><p>Zero or more of the following letters:</p>
      <p><code>D</code>: Include directories (folders).<br>
      <code>F</code>: Include files. If both F and D are omitted, files are included but not folders.<br>
      <code>R</code>: Recurse into subdirectories (subfolders). If R is omitted, files and folders in subfolders are not included.</p></dd>

</dl>

<h2 id="old">Old Syntax</h2>
<p class="warning"><strong>Deprecated:</strong> This syntax is not recommended for use in new scripts. Use the <a href="#new">new syntax</a> instead.</p>
<pre class="Syntax"><span class="func">Loop</span>, FilePattern <span class="optional">, IncludeFolders?, Recurse?</span></pre>

<h3>Parameters</h3>
<dl>

  <dt>FilePattern</dt>
  <dd><p>The name of a single file or folder, or a wildcard pattern such as <code>C:\Temp\*.tmp</code>. <em>FilePattern</em> is assumed to be in <a href="../Variables.htm#WorkingDir">%A_WorkingDir%</a> if an absolute path isn't specified.</p>
      <p>Both asterisks and question marks are supported as wildcards. A match occurs when the pattern appears in either the file's long/normal name or its <a href="#LoopFileShortName">8.3 short name</a>.</p>
      <p>If this parameter is a single file or folder (i.e. no wildcards) and <em>Recurse</em> is set to 1, more than one match will be found if the specified file name appears in more than one of the folders being searched.</p></dd>

  <dt>IncludeFolders?</dt>
  <dd><p>One of the following digits, or blank to use the default:<br>
      0 (default) Folders are not retrieved (only files).<br>
      1 All files and folders that match the wildcard pattern are retrieved.<br>
      2 Only folders are retrieved (no files).</p></dd>

  <dt>Recurse?</dt>
  <dd>One of the following digits, or blank to use the default:<br>
      0 (default) Subfolders are not recursed into.<br>
      1 Subfolders are recursed into so that files and folders contained therein are retrieved if they match <em>FilePattern</em>. All subfolders will be recursed into, not just those whose names match <em>FilePattern</em>.</dd>

</dl>

<h2>Special Variables Available Inside a File-Loop</h2>
<p>The following variables exist within any file-loop. If an inner file-loop is enclosed by an outer file-loop, the innermost loop's file will take precedence:</p>
<table class="info">
  <tr id="LoopFileName">
    <td>A_LoopFileName</td>
    <td>The name of the file or folder currently retrieved (without the path).</td>
  </tr>
  <tr id="LoopFileExt">
    <td>A_LoopFileExt</td>
    <td>The file's extension (e.g. TXT, DOC, or EXE). The period (.) is not included.</td>
  </tr>
  <tr id="LoopFileFullPath">
    <td>A_LoopFileFullPath<br>
    A_LoopFilePath</td>
    <td><p>The path and name of the file/folder currently retrieved. If <em>FilePattern</em> contains a relative path rather than an absolute path, the path here will also be relative. In addition, any short (8.3) folder names in <em>FilePattern</em> will still be short (see next item to get the long version).</p>
    <p>A_LoopFilePath is available in <span class="ver">[v1.1.28+]</span> as an alias of A_LoopFileFullPath, which is a misnomer.</p></td>
  </tr>
  <tr id="LoopFileLongPath">
    <td>A_LoopFileLongPath</td>
    <td><p>This is different than A_LoopFileFullPath in the following ways: 1) It always contains the absolute/complete path of the file even if <em>FilePattern</em> contains a relative path; 2) Any short (8.3) folder names in <em>FilePattern</em> itself are converted to their long names; 3) Characters in <em>FilePattern</em> are converted to uppercase or lowercase to match the case stored in the file system. This is useful for converting file names -- such as those passed into a script as command line parameters -- to their exact path names as shown by Explorer.</p></td>
  </tr>
  <tr id="LoopFileShortPath">
    <td>A_LoopFileShortPath</td>
    <td><p>The 8.3 short path and name of the file/folder currently retrieved. For example: C:\MYDOCU~1\ADDRES~1.txt. If <em>FilePattern</em> contains a relative path rather than an absolute path, the path here will also be relative.</p>
      <p>To retrieve the complete 8.3 path and name for a single file or folder, specify its name for <em>FilePattern</em> as in this example:</p>
<pre>Loop, C:\My Documents\Address List.txt
    ShortPathName := A_LoopFileShortPath</pre>
        <p class="note"><strong>Note</strong>: This variable will be <strong>blank</strong> if the file does not have a short name, which can happen on systems where NtfsDisable8dot3NameCreation has been set in the registry. It will also be blank if <em>FilePattern</em> contains a relative path and the body of the loop uses <a href="SetWorkingDir.htm">SetWorkingDir</a> to switch away from the working directory in effect for the loop itself.</p></td>
  </tr>
  <tr id="LoopFileShortName">
    <td>A_LoopFileShortName</td>
    <td>The 8.3 short name, or alternate name of the file. If the file doesn't have one (due to the long name being shorter than 8.3 or perhaps because short-name generation is disabled on an NTFS file system), <em>A_LoopFileName</em> will be retrieved instead.</td>
  </tr>
  <tr id="LoopFileDir">
    <td>A_LoopFileDir</td>
    <td>The path of the directory in which <em>A_LoopFileName</em> resides. If <em>FilePattern</em> contains a relative path rather than an absolute path, the path here will also be relative. A root directory will not contain a trailing backslash. For example: C:</td>
  </tr>
  <tr id="LoopFileTimeModified">
    <td>A_LoopFileTimeModified</td>
    <td>The time the file was last modified. Format <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td>
  </tr>
  <tr id="LoopFileTimeCreated">
    <td>A_LoopFileTimeCreated</td>
    <td>The time the file was created. Format <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td>
  </tr>
  <tr id="LoopFileTimeAccessed">
    <td>A_LoopFileTimeAccessed</td>
    <td>The time the file was last accessed. Format <a href="FileSetTime.htm">YYYYMMDDHH24MISS</a>.</td>
  </tr>
  <tr id="LoopFileAttrib">
    <td>A_LoopFileAttrib</td>
    <td>The <a href="FileGetAttrib.htm">attributes</a> of the file currently retrieved.</td>
  </tr>
  <tr id="LoopFileSize">
    <td>A_LoopFileSize</td>
    <td>The size in bytes of the file currently retrieved. Files larger than 4 gigabytes are also supported.</td>
  </tr>
  <tr id="LoopFileSizeKB">
    <td>A_LoopFileSizeKB</td>
    <td>The size in Kbytes of the file currently retrieved, rounded down to the nearest integer.</td>
  </tr>
  <tr id="LoopFileSizeMB">
    <td>A_LoopFileSizeMB</td>
    <td>The size in Mbytes of the file currently retrieved, rounded down to the nearest integer.</td>
  </tr>
</table>

<h2>Remarks</h2>
<p>A file-loop is useful when you want to operate on a collection of files and/or folders, one at a time.</p>
<p>All matching files are retrieved, including hidden files. By contrast, OS features such as the DIR command omit hidden files by default. To avoid processing hidden, system, and/or read-only files, use something like the following inside the loop:</p>
<pre>if A_LoopFileAttrib contains H,R,S  <em>; Skip any file that is either H (Hidden), R (Read-only), or S (System). Note: No spaces in &quot;H,R,S&quot;.</em>
    continue  <em>; Skip this file and move on to the next one.</em></pre>
<p>To retrieve files' relative paths instead of absolute paths during a recursive search, use <a href="SetWorkingDir.htm">SetWorkingDir</a> to change to the base folder prior to the loop, and then omit the path from the Loop (e.g. <code>Loop, *.*, 0, 1</code>). That will cause <a href="#LoopFileFullPath">A_LoopFileFullPath</a> to contain the file's path relative to the base folder.</p>
<p>A file-loop can disrupt itself if it creates or renames files or folders within its own purview. For example, if it renames files via <a href="FileMove.htm">FileMove</a> or other means, each such file might be found twice: once as its old name and again as its new name. To work around this, rename the files only after creating a list of them. For example:</p>
<pre>FileList := ""
Loop, Files, *.jpg
    FileList .= A_LoopFileName "`n"
Loop, Parse, FileList, `n
    FileMove, %A_LoopField%, renamed_%A_LoopField%</pre>
<p>Files in an NTFS file system are probably always retrieved in alphabetical order. Files in other file systems are retrieved in no particular order. To ensure a particular ordering, use the <a href="Sort.htm">Sort</a> command as shown in the Examples section below.</p>
<p>Files and folders with a complete path name longer than 259 characters are skipped over as though they do not exist. Such files are rare because normally, the operating system does not allow their creation.</p>
<p>See <a href="Loop.htm">Loop</a> for information about <a href="Block.htm">Blocks</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a>, and the A_Index variable (which exists in every type of loop).</p>

<h2>Related</h2>
<p><a href="Loop.htm">Loop</a>, <a href="Break.htm">Break</a>, <a href="Continue.htm">Continue</a>, <a href="Block.htm">Blocks</a>, <a href="SplitPath.htm">SplitPath</a>, <a href="FileSetAttrib.htm">FileSetAttrib</a>, <a href="FileSetTime.htm">FileSetTime</a></p>

<h2>Examples</h2>
<div class="ex" id="ExBasic">
<p><a href="#ExBasic">#1</a></p>
<pre>Loop Files, %A_ProgramFiles%\*.txt, R  <em>; Recurse into subfolders.</em>
{
    MsgBox, 4, , Filename = %A_LoopFileFullPath%`n`nContinue?
    IfMsgBox, No
        break
}</pre>
</div>

<div class="ex" id="ExSize">
<p><a href="#ExSize">#2</a>: Calculate the size of a folder, including the files in all its subfolders:</p>
<pre>SetBatchLines, -1  <em>; Make the operation run at maximum speed.</em>
FolderSizeKB := 0
FileSelectFolder, WhichFolder  <em>; Ask the user to pick a folder.</em>
Loop, Files, %WhichFolder%\*.*, R
    FolderSizeKB += A_LoopFileSizeKB
MsgBox Size of %WhichFolder% is %FolderSizeKB% KB.</pre>
</div>

<div class="ex" id="ExSortName">
<p><a href="#ExSortName">#3</a>: Retrieve file names sorted by name (see next example to sort by date):</p>
<pre>FileList := ""  <em>; Initialize to be blank.</em>
Loop, C:\*.*
    FileList .= A_LoopFileName "`n"
Sort, FileList, R  <em>; The R option sorts in reverse order. See <a href="Sort.htm">Sort</a> for other options.</em>
Loop, parse, FileList, `n
{
    if (A_LoopField = "")  <em>; Ignore the blank item at the end of the list.</em>
        continue
    MsgBox, 4,, File number %A_Index% is %A_LoopField%.  Continue?
    IfMsgBox, No
        break
}</pre>
</div>

<div class="ex" id="ExSortDate">
<p><a href="#ExSortDate">#4</a>: Retrieve file names sorted by modification date:</p>
<pre>FileList := ""
Loop, Files, %A_MyDocuments%\Photos\*.*, FD  <em>; Include Files and Directories</em>
    FileList .= A_LoopFileTimeModified "`t" A_LoopFileName "`n"
Sort, FileList  <em>; Sort by date.</em>
Loop, Parse, FileList, `n
{
    if (A_LoopField = "")  <em>; Omit the last linefeed (blank item) at the end of the list.</em>
        continue
    StringSplit, FileItem, A_LoopField, %A_Tab%  <em>; Split into two parts at the tab char.</em>
    MsgBox, 4,, The next file (modified at %FileItem1%) is:`n%FileItem2%`n`nContinue?
    IfMsgBox, No
        break
}</pre>
</div>

<div class="ex" id="ExFileCopy">
<p><a href="#ExFileCopy">#5</a>: Copy only the source files that are newer than their counterparts in the destination:</p>
<pre>CopyIfNewer:
<em>; Caller has set the variables CopySourcePattern and CopyDest for us.</em>
Loop, Files, %CopySourcePattern%
{
    copy_it := false
    if not FileExist(CopyDest "\" A_LoopFileName)  <em>; Always copy if target file doesn't yet exist.</em>
        copy_it := true
    else
    {
        FileGetTime, time, %CopyDest%\%A_LoopFileName%
        EnvSub, time, %A_LoopFileTimeModified%, seconds  <em>; Subtract the source file's time from the destination's.</em>
        if (time &lt; 0)  <em>; Source file is newer than destination file.</em>
            copy_it := true
    }
    if copy_it
    {
        FileCopy, %A_LoopFileFullPath%, %CopyDest%\%A_LoopFileName%, 1   <em>; Copy with overwrite=yes</em>
        if ErrorLevel
            MsgBox, Could not copy &quot;%A_LoopFileFullPath%&quot; to &quot;%CopyDest%\%A_LoopFileName%&quot;.
    }
}
Return</pre>
</div>

<div class="ex" id="ExLongPath">
<p><a href="#ExLongPath">#6</a>: Convert filenames passed in via command-line parameters to long names, complete path, and correct uppercase/lowercase characters as stored in the file system.</p>
<pre>Loop %0%  <em>; For each file dropped onto the script (or passed as a parameter).</em>
{
    GivenPath := %A_Index%  <em>; Retrieve the next command line parameter.</em>
    Loop %GivenPath%, 1
        LongPath := A_LoopFileLongPath
    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%
}</pre>
</div>

</body>
</html>
